package com.hgy.stack;

public class InfixCalculatorDemo {
    public static void main(String[] args) {
        InfixCalculator calculator = new InfixCalculator();
        int res = calculator.calExpression("((7+8)*2+9)*2");
        System.out.println(res);
    }
}

class InfixCalculator {

    //计算表达式expression
    public int calExpression(String expression){
        int res = 0;
        int index = 0;
        //创建两个栈，数栈，符号栈
        LinkedListStack<Integer> numStack = new LinkedListStack<Integer>();
        LinkedListStack<Character> opeStack = new LinkedListStack<Character>();
        for (int i = 0; i < expression.length(); i++) {
            char temp = expression.charAt(i);//读取expression下标为i的字符
            if (isPoe(temp)){//若该字符是运算符
                index = i+1;
                if (opeStack.isEmpty()){//若运算符栈为空
                    opeStack.push(temp);
                }else {//若不为空，则判断运算符优先级
                    int pri1 = priority(temp);//当前读取运算符的优先级
                    int pri2 = priority(opeStack.top());//栈顶运算符的优先级
                    if (pri1 > pri2) {//若栈顶运算符优先级较小
                        opeStack.push(temp);
                    }else {
                        char ope = opeStack.pop();
                        opeStack.push(temp);
                        numStack.push(cal(numStack.pop(), numStack.pop(), ope));
                    }
                }
            }else if (temp == '(') {
                opeStack.push(temp);
                index = i+1;
            }else if(temp == ')') {
                index = i+1;
                boolean loop = true;
                while(loop) {
                    char ope = opeStack.pop();
                    if (ope == '(') {
                        loop = false;
                    } else {
                        try {
                            numStack.push(cal(numStack.pop(), numStack.pop(), ope));
                        } catch (Exception e) {
                            throw new RuntimeException("表达式错误！");
                        }
                    }
                }
            }else {
                    if (i == expression.length()-1){
                        int num = Integer.parseInt(expression.substring(index, i+1));
                        numStack.push(num);
                        break;
                    }
                    //读取数字
                    if(isPoe(expression.charAt(i+1)) || expression.charAt(i+1) == '('
                                                     || expression.charAt(i+1) == ')'){
                        int num = Integer.parseInt(expression.substring(index, i+1));
                        numStack.push(num);
                    }
            }
        }
        while (!opeStack.isEmpty()){
            try{
                numStack.push(cal(numStack.pop(), numStack.pop(), opeStack.pop()));
            }catch (Exception e){
                throw new RuntimeException("表达式错误~~");
            }
        }
        res = numStack.pop();
        return res;
    }

    //返回运算符的优先级
    //优先级使用数字表示，数字越大，优先级越高
    private int priority(int ope){
        if (ope == '*' || ope == '/'){
            return 1;
        }
        if (ope == '+' || ope == '-'){
            return 0;
        }
        return -1;
    }

    //判断是否是一个运算符
    private boolean isPoe(char val){
        return val == '+' || val == '-' ||
                val == '*' || val == '/';
    }

    //num2 ope num1
    private int cal(int num1, int num2, char ope){
        int res = 0;
        switch (ope){
            case '+':
                res = num1 + num2;
                break;
            case '-':
                res = num2 - num1;
                break;
            case '*':
                res = num1*num2;
                break;
            case '/':
                res = num2/num1;
                break;
            default:
                break;
        }
        return res;
    }
}
